﻿//--------------------------------------------------------------------------------------------------------------
// <copyright file="CSPProcedureWebPart.cs" company="Microsoft Corporation" author="David Martos" date="01/02/2008">
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>
//--------------------------------------------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using Microsoft.Win32;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Publishing;
using System.Web.UI.WebControls.WebParts;
using Microsoft.SharePoint.WebPartPages;
using Microsoft.SharePoint.Administration;

namespace CSP.Package
{
    /// <summary>
    /// This is the main form used to install CSP Package.
    /// </summary>
    public partial class Installer : Form
    {
        /// <summary>
        /// Current step
        /// </summary>
        private int step = 0;
        /// <summary>
        /// List of labels to show in the left hand side of the screen
        /// </summary>
        List<Label> labels = new List<Label>();
        /// <summary>
        /// List of controls to show in the right hand side of the screen
        /// </summary>
        List<IInstallationControl> controls = new List<IInstallationControl>();

        public string IntranetBaseUrl
        {
            get
            {
                return RegistryAccess.GetStringProperty(Registry.LocalMachine, Constants.CspRegistryKey, "CSPIntranetWebApplication");
            }
        }
        public string InternetBaseUrl
        {
            get
            {
                return RegistryAccess.GetStringProperty(Registry.LocalMachine, Constants.CspRegistryKey, "CSPInternetWebApplication");
            }
        }
        public string CentralBaseUrl
        {
            get
            {
                return RegistryAccess.GetStringProperty(Registry.LocalMachine, Constants.CspRegistryKey, "CentralAdminUrl");
            }
        }



        public Installer()
        {
            InitializeComponent();

            lblApplicationTitle.Text = CSP.Package.labels.CSPInstallControl_AppTitle;
        }

        protected string _logMessages;

        public void AddToLog(string message)
        {
            _logMessages += string.Format("{0}\r\n", message);
        }

        public string GetLog()
        {
            return _logMessages;
        }

        public void ShowException(Exception ex)
        {
            AddToLog(ex.ToString());
            MessageBox.Show(CSP.Package.labels.CspInstallError_Unexpected, CSP.Package.labels.CspInstallError_Title, MessageBoxButtons.OK, MessageBoxIcon.Error);
        }

        /// <summary>
        /// Adds the given IInstallationControl to the list of controls to show into the application
        /// </summary>
        /// <param name="control"></param>
        /// <param name="label"></param>
        private void AddInstallationControl(IInstallationControl control, Label label)
        {
            labels.Add(label);

            CSP.Package.Controls.Initialization initialization = new CSP.Package.Controls.Initialization();
            control.SetForm(this);
            ((UserControl)control).Dock = DockStyle.Fill;
            panel5.Controls.Add(((UserControl)control));
            controls.Add(control);
        }

        /// <summary>
        /// Operation overload to set the initial display mode of the control to hidden state
        /// </summary>
        /// <param name="control"></param>
        /// <param name="label"></param>
        /// <param name="hidden"></param>
        private void AddInstallationControl(IInstallationControl control, Label label, bool hidden)
        {
            AddInstallationControl(control, label);
            if (hidden) ((UserControl)control).Hide();
        }

        public void BeginInstallation(int installation)
        {
            panel4.Visible = true;
            panel2.Visible = true;
            installationSelector.Visible = false;


            if (RegistryAccess.PropertyExists(Registry.LocalMachine, Constants.CspRegistryKey, "InstallationProcessStep"))
            {
                step = Convert.ToInt32(RegistryAccess.GetStringProperty(Registry.LocalMachine, Constants.CspRegistryKey, "InstallationProcessStep"));
            }
            else
            {
                RegistryAccess.CreateStringProperty(Registry.LocalMachine, Constants.CspRegistryKey, "InstallationProcessStep", "0");
                step = 0;
            }

            if (installation != 3)
            {
                AddInstallationControl(new CSP.Package.Controls.Initialization(), lblInitializations);
                AddInstallationControl(new CSP.Package.Controls.CreateInternetWebApplication(), lblCreateInternetWebApplication, true);
                AddInstallationControl(new CSP.Package.Controls.CreateIntranetWebApplication(), lblCreateIntranetWebApplication, true);
                AddInstallationControl(new CSP.Package.Controls.CSPSolution(), lblCSPPackage, true);
                AddInstallationControl(new CSP.Package.Controls.FBADatabase(), lblFBADatabase, true);
                AddInstallationControl(new CSP.Package.Controls.FBASolution(), lblFBAPackage, true);
            }
            else
            {
                flowLayoutPanel1.Controls.Remove(lblCreateInternetWebApplication);
                flowLayoutPanel1.Controls.Remove(lblCreateIntranetWebApplication);
                flowLayoutPanel1.Controls.Remove(lblCSPPackage);
                flowLayoutPanel1.Controls.Remove(lblFBADatabase);
                flowLayoutPanel1.Controls.Remove(lblFBAPackage);
            }
            if (installation == 1)
            {
                AddInstallationControl(new CSP.Package.Controls.SimpleCMSDatabase(), lblSimpleCMSDatabase, true);
                AddInstallationControl(new CSP.Package.Controls.SimpleCMSPackage(), lblSimpleCMSPackage, true);
            }
            else
            {
                flowLayoutPanel1.Controls.Remove(lblSimpleCMSDatabase);
                flowLayoutPanel1.Controls.Remove(lblSimpleCMSPackage);
            }
            if (installation != 1)
            {
                AddInstallationControl(new CSP.Package.Controls.CRMCustomizations(), lblCRMCustomizations, true);
                AddInstallationControl(new CSP.Package.Controls.CRMConnectorPackage(), lblCRMConnector, true);
            }
            else
            {
                flowLayoutPanel1.Controls.Remove(lblCRMCustomizations);
                flowLayoutPanel1.Controls.Remove(lblCRMConnector);
            }

            if (installation != 3)
            {
                AddInstallationControl(new CSP.Package.Controls.CreateInternetSiteCollection(), lblCreateInternetSiteCollection, true);
                AddInstallationControl(new CSP.Package.Controls.CreateIntranetSiteCollection(), lblCreateIntranetSiteCollection, true);
                AddInstallationControl(new CSP.Package.Controls.ExtendInternetWebApplication(), lblExtendInternetWebApplication, true);
                AddInstallationControl(new CSP.Package.Controls.ExcelLocations(), lblExcelLocations, true);

                AddInstallationControl(new CSP.Package.Controls.PostInstallationSteps(), lblPostInstallationSteps, true);
            }
            else
            {
                flowLayoutPanel1.Controls.Remove(lblCreateInternetSiteCollection);
                flowLayoutPanel1.Controls.Remove(lblCreateIntranetSiteCollection);
                flowLayoutPanel1.Controls.Remove(lblExtendInternetWebApplication);
                flowLayoutPanel1.Controls.Remove(lblExcelLocations);
                flowLayoutPanel1.Controls.Remove(lblPostInstallationSteps);
            }
            AddInstallationControl(new CSP.Package.Controls.InstallationSummary(), lblSummary, true);

            SetInitialControl();
        }

        CSP.Package.Controls.InstallationSelector installationSelector;

        /// <summary>
        /// When the installed loads, all the labels and controls are added to the corresponding lists.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Installer_Load(object sender, EventArgs e)
        {
            this.TranslateLiterals();
            this._logMessages = string.Empty;

            panel4.Visible = false;
            panel2.Visible = false;
            installationSelector = new CSP.Package.Controls.InstallationSelector();
            installationSelector.SetForm(this);
            installationSelector.Dock = DockStyle.Fill;
            panel5.Controls.Add(installationSelector);


            

        }


        protected void SetInitialControl()
        {
            ((UserControl)controls[0]).Hide();
            for (int i = 0; i < step; i++)
            {
                labels[i].ForeColor = System.Drawing.SystemColors.InactiveCaption;
            }
            labels[step].ForeColor = System.Drawing.SystemColors.ActiveCaption;
            ((UserControl)controls[step]).Show();
        }

        /// <summary>
        /// Method fired when the user clicks the Next button.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnProceed_Click(object sender, EventArgs e)
        {
            this.Cursor = Cursors.WaitCursor;

            try
            {
                if (btnProceed.Text == CSP.Package.labels.CSPInstallControl_Finish)
                {
                    btnProceed.Enabled = false;
                    RegistryAccess.DeleteStringProperty(Registry.LocalMachine, Constants.CspRegistryKey, "InstallationProcessStep");
                }

                if (step < labels.Count)
                {
                    bool next = chkSkip.Checked ? true : controls[step].Next();

                    if (next)
                    {
                        if (step < labels.Count - 1)
                        {
                            labels[step].ForeColor = System.Drawing.SystemColors.InactiveCaption;
                            ((UserControl)controls[step++]).Hide();
                            //step += 1;
                            RegistryAccess.SetStringProperty(Registry.LocalMachine, Constants.CspRegistryKey, "InstallationProcessStep", step.ToString());
                            labels[step].ForeColor = System.Drawing.SystemColors.ActiveCaption;
                            ((UserControl)controls[step]).Show();
                        }
                        if (step == labels.Count - 1)
                        {
                            btnProceed.Text = CSP.Package.labels.CSPInstallControl_Finish;
                        }
                    }
                }
            }
            catch
            {
                for (int i = step; i < labels.Count - 1; i++)
                {
                    labels[i].ForeColor = System.Drawing.SystemColors.InactiveCaption;
                    ((UserControl)controls[i]).Hide();
                }
                step = labels.Count - 1;
                labels[step].ForeColor = System.Drawing.SystemColors.ActiveCaption;
                ((UserControl)controls[step]).Show();
                ((IInstallationControl)controls[step]).Next();
                btnProceed.Text = CSP.Package.labels.CSPInstallControl_Finish;
                btnProceed.Enabled = false;

            }

            this.Cursor = Cursors.Default;

        }

        private void TranslateLiterals()
        {
            this.lblApplicationTitle.Text = CSP.Package.labels.InstallerApplicationTitle_Label;
            this.lblCreateInternetSiteCollection.Text = CSP.Package.labels.InstallerCreateInternetSiteCollection_Label;
            this.lblCreateInternetWebApplication.Text = CSP.Package.labels.InstallerCreateInternetWebApplication_Label;
            this.lblCreateIntranetSiteCollection.Text = CSP.Package.labels.InstallerCreateIntranetSiteCollection_Label;
            this.lblCreateIntranetWebApplication.Text = CSP.Package.labels.InstallerCreateIntranetWebApplication_Label;
            this.lblCRMConnector.Text = CSP.Package.labels.InstallerCRMConnector_Label;
            this.lblCRMCustomizations.Text = CSP.Package.labels.InstallerCRMCustomizations_Label;
            this.lblCSPPackage.Text = CSP.Package.labels.InstallerCSPPackage_Label;
            this.lblExcelLocations.Text = CSP.Package.labels.InstallerExcelLocations_Label;
            this.lblExtendInternetWebApplication.Text = CSP.Package.labels.InstallerExtendInternetWebApplication_Label;
            this.lblFBADatabase.Text = CSP.Package.labels.InstallerFBADatabase_Label;
            this.lblFBAPackage.Text = CSP.Package.labels.InstallerFBAPackage_Label;
            this.lblInitializations.Text = CSP.Package.labels.InstallerInitializations_Label;
            this.lblPostInstallationSteps.Text = CSP.Package.labels.InstallerPostInstallationSteps_Label;
            this.lblSimpleCMSDatabase.Text = CSP.Package.labels.InstallerSimpleCMSDatabase_Label;
            this.lblSimpleCMSPackage.Text = CSP.Package.labels.InstallerSimpleCMSPackage_Label;
            this.lblSummary.Text = CSP.Package.labels.InstallerSummary_Label;

            this.chkSkip.Text = CSP.Package.labels.InstallerSkip_Label;
            this.btnProceed.Text = CSP.Package.labels.InstallerProceed_Label;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            SPSite site = new SPSite("http://localhost:7000");
            SPWebApplication WebApp = site.WebApplication;

            foreach (ModificationEntry entry in GetSectionEntries())
            {
                WebApp.WebConfigModifications.Add(ModificationEntryHelper.CreateModification(entry.Name, entry.XPath, entry.Value, SPWebConfigModification.SPWebConfigModificationType.EnsureSection)
                );
            }

            foreach (ModificationEntry entry in GetChildNodeEntries())
            {
                WebApp.WebConfigModifications.Add(ModificationEntryHelper.CreateModification(entry.Name, entry.XPath, entry.Value, SPWebConfigModification.SPWebConfigModificationType.EnsureChildNode)
                );
            }

            foreach (ModificationEntry entry in GetAttributeEntries())
            {
                WebApp.WebConfigModifications.Add(ModificationEntryHelper.CreateModification(entry.Name, entry.XPath, entry.Value, SPWebConfigModification.SPWebConfigModificationType.EnsureAttribute)
                );
            }

            WebApp.Farm.Services.GetValue<SPWebService>().ApplyWebConfigModifications();
            WebApp.Update();

        }



        protected string _defaultMembershipProvider = "AspNetMembershipProvider";
        protected string _connectionStringName = "AspNetMembershipSQL";
        protected string _connectionStringContent = "Data Source=(local);Initial Catalog=AspNetDb_CSP;Trusted_Connection=yes;";

        protected string _servicePrincipalName = "host/localhost";
        protected string _defaultMembershipRoleProvider = "AspNetMembershipRoleProvider";
        protected string _defaultEndPointAddress = "http://localhost/MembershipServiceClass.svc";

        /// <summary>
        /// Gets the connection string from the machine's registry
        /// </summary>
        protected string ConnectionStringContent
        {
            get
            {
                try
                {
                    return RegistryAccess.GetStringProperty(Registry.LocalMachine, Constants.CspRegistryKey, "FBAConnectionString");
                }
                catch (Exception ex)
                {
                    return _connectionStringContent;
                }
            }
        }

        /// <summary>
        /// Gets the service principal name from the machine's registry
        /// </summary>
        protected string ServicePrincipalName
        {
            get
            {
                try
                {
                    return RegistryAccess.GetStringProperty(Registry.LocalMachine, Constants.CspRegistryKey, "WCFServicePrincipalName");
                }
                catch (Exception ex)
                {
                    return _servicePrincipalName;
                }
            }
        }

        /// <summary>
        /// Gets the default end point address from the machine's registry
        /// </summary>
        protected string DefaultEndPointAddress
        {
            get
            {
                try
                {
                    return RegistryAccess.GetStringProperty(Registry.LocalMachine, Constants.CspRegistryKey, "WCFEndPointURL");
                }
                catch (Exception ex)
                {
                    return _defaultEndPointAddress;
                }
            }
        }

        /// <summary>
        /// Holds the ModificationEntry objects that must be applied as section nodes.
        /// </summary>
        protected ModificationEntry[] GetSectionEntries()
        {
            List<ModificationEntry> modifications = new List<ModificationEntry>();
            //Add Section nodes
            modifications.Add(new ModificationEntry("appSettings", "configuration", "appSettings"));
            modifications.Add(new ModificationEntry("connectionStrings", "configuration", "connectionStrings"));
            modifications.Add(new ModificationEntry("membership", "configuration/system.web", "membership"));
            modifications.Add(new ModificationEntry("providers", "configuration/system.web/membership", "providers"));
            modifications.Add(new ModificationEntry("roleManager", "configuration/system.web", "roleManager"));
            modifications.Add(new ModificationEntry("providers", "configuration/system.web/roleManager", "providers"));
            modifications.Add(new ModificationEntry("system.serviceModel", "configuration", "system.serviceModel"));
            modifications.Add(new ModificationEntry("bindings", "configuration/system.serviceModel", "bindings"));
            modifications.Add(new ModificationEntry("wsHttpBinding", "configuration/system.serviceModel/bindings", "wsHttpBinding"));
            modifications.Add(new ModificationEntry("binding", "configuration/system.serviceModel/bindings/wsHttpBinding", "binding"));
            modifications.Add(new ModificationEntry("client", "configuration/system.serviceModel", "client"));
            modifications.Add(new ModificationEntry("endpoint", "configuration/system.serviceModel/client", "endpoint"));
            modifications.Add(new ModificationEntry("identity", "configuration/system.serviceModel/client/endpoint", "identity"));
            return modifications.ToArray();

        }

        /// <summary>
        /// Holds the ModificationEntry objects that must be applied as child nodes.
        /// </summary>
        protected ModificationEntry[] GetChildNodeEntries()
        {
            List<ModificationEntry> modifications = new List<ModificationEntry>();
            modifications.Add(
                new ModificationEntry(
                    string.Format("add[@name='{0}']", _connectionStringName),
                    "configuration/connectionStrings",
                    string.Format(@"<add name=""{0}"" connectionString=""{1}"" />", _connectionStringName, ConnectionStringContent))
                    );

            modifications.Add(
                new ModificationEntry(
                    string.Format("add[@name='{0}']", _defaultMembershipProvider),
                    "configuration/system.web/membership/providers",
                    string.Format(@"<add name=""{0}"" connectionStringName=""{1}"" enablePasswordRetrieval=""false"" enablePasswordReset=""true"" requiresQuestionAndAnswer=""false"" applicationName=""/"" requiresUniqueEmail=""false"" passwordFormat=""Hashed"" maxInvalidPasswordAttempts=""5"" minRequiredPasswordLength=""1"" minRequiredNonalphanumericCharacters=""0"" passwordAttemptWindow=""10"" passwordStrengthRegularExpression="""" type=""System.Web.Security.SqlMembershipProvider,System.Web,Version=2.0.0.0,Culture=neutral,PublicKeyToken=b03f5f7f11d50a3a"" />", _defaultMembershipProvider, _connectionStringName))
                    );

            modifications.Add(
                new ModificationEntry(
                    string.Format("add[@name='{0}']", _defaultMembershipRoleProvider),
                    "configuration/system.web/roleManager/providers",
                    string.Format(@"<add name=""{0}"" connectionStringName=""{1}"" applicationName=""/"" type=""System.Web.Security.SqlRoleProvider,System.Web,Version=2.0.0.0,Culture=neutral,PublicKeyToken=b03f5f7f11d50a3a"" />", _defaultMembershipRoleProvider, _connectionStringName))
                    );


            modifications.Add(
                new ModificationEntry(
                    "add[@name='readerQuotas']",
                    "configuration/system.serviceModel/bindings/wsHttpBinding/binding",
                    @"<readerQuotas maxDepth=""32"" maxStringContentLength=""8192"" maxArrayLength=""16384"" maxBytesPerRead=""4096"" maxNameTableCharCount=""16384"" />")
                    );

            modifications.Add(
                new ModificationEntry(
                    "add[@name='reliableSession']",
                    "configuration/system.serviceModel/bindings/wsHttpBinding/binding",
                    @"<reliableSession ordered=""true"" inactivityTimeout=""00:10:00"" enabled=""false"" />")
                    );

            modifications.Add(
                new ModificationEntry(
                    "add[@name='security']",
                    "configuration/system.serviceModel/bindings/wsHttpBinding/binding",
                    @"<security mode=""None"" />")
                    );

            modifications.Add(
                new ModificationEntry(
                    "add[@name='identity']",
                    "configuration/system.serviceModel/client/endpoint/identity",
                    string.Format(@"<servicePrincipalName value=""{0}"" />", ServicePrincipalName))
                    );



            return modifications.ToArray();
        }

        /// <summary>
        /// Holds the ModificationEntry objects that must be applied as attributes.
        /// </summary>
        protected ModificationEntry[] GetAttributeEntries()
        {

            List<ModificationEntry> modifications = new List<ModificationEntry>();
            modifications.Add(new ModificationEntry("defaultProvider", "configuration/system.web/membership", _defaultMembershipProvider));
            modifications.Add(new ModificationEntry("enabled", "configuration/system.web/roleManager", "true"));
            modifications.Add(new ModificationEntry("defaultProvider", "configuration/system.web/roleManager", _defaultMembershipRoleProvider));
            modifications.Add(new ModificationEntry("mode", "configuration/system.web/authentication", "Forms"));
            modifications.Add(new ModificationEntry("loginUrl", "configuration/system.web/authentication/forms", "/Pages/sign_up.aspx"));
            modifications.Add(new ModificationEntry("address", "configuration/system.serviceModel/client/endpoint", DefaultEndPointAddress));

            //TODO: Test it
            modifications.Add(new ModificationEntry("name", "configuration/system.serviceModel/bindings/wsHttpBinding/binding", "WSHttpBinding_IMembershipServiceContract"));
            modifications.Add(new ModificationEntry("closeTimeout", "configuration/system.serviceModel/bindings/wsHttpBinding/binding", "00:01:00"));
            modifications.Add(new ModificationEntry("openTimeout", "configuration/system.serviceModel/bindings/wsHttpBinding/binding", "00:01:00"));
            modifications.Add(new ModificationEntry("receiveTimeout", "configuration/system.serviceModel/bindings/wsHttpBinding/binding", "00:10:00"));
            modifications.Add(new ModificationEntry("sendTimeout", "configuration/system.serviceModel/bindings/wsHttpBinding/binding", "00:01:00"));
            modifications.Add(new ModificationEntry("bypassProxyOnLocal", "configuration/system.serviceModel/bindings/wsHttpBinding/binding", "false"));
            modifications.Add(new ModificationEntry("transactionFlow", "configuration/system.serviceModel/bindings/wsHttpBinding/binding", "false"));
            modifications.Add(new ModificationEntry("hostNameComparisonMode", "configuration/system.serviceModel/bindings/wsHttpBinding/binding", "StrongWildcard"));
            modifications.Add(new ModificationEntry("maxBufferPoolSize", "configuration/system.serviceModel/bindings/wsHttpBinding/binding", "524288"));
            modifications.Add(new ModificationEntry("maxReceivedMessageSize", "configuration/system.serviceModel/bindings/wsHttpBinding/binding", "2147483647"));
            modifications.Add(new ModificationEntry("messageEncoding", "configuration/system.serviceModel/bindings/wsHttpBinding/binding", "Text"));
            modifications.Add(new ModificationEntry("textEncoding", "configuration/system.serviceModel/bindings/wsHttpBinding/binding", "utf-8"));
            modifications.Add(new ModificationEntry("useDefaultWebProxy", "configuration/system.serviceModel/bindings/wsHttpBinding/binding", "true"));
            modifications.Add(new ModificationEntry("allowCookies", "configuration/system.serviceModel/bindings/wsHttpBinding/binding", "false"));

            modifications.Add(new ModificationEntry("binding", "configuration/system.serviceModel/client/endpoint", "wsHttpBinding"));
            modifications.Add(new ModificationEntry("bindingConfiguration", "configuration/system.serviceModel/client/endpoint", "WSHttpBinding_IMembershipServiceContract"));
            modifications.Add(new ModificationEntry("contract", "configuration/system.serviceModel/client/endpoint", "CSP.MembershipInterface.IMembershipServiceContract"));
            modifications.Add(new ModificationEntry("name", "configuration/system.serviceModel/client/endpoint", "WSHttpBinding_IMembershipServiceContract"));
            return modifications.ToArray();
        }

    }
}
